<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2018/10/19
 * Time: 19:38
 */

namespace app\api\controller;

use app\admin\model\Order;
use app\common\controller\ReturnCode;
use think\Config;
use think\Controller;
use think\Db;
use think\Log;
use think\Request;
use think\Loader;
Loader::import('Service/PayNotifyCallBack',EXTEND_PATH);
Loader::import('Service/WxPay',EXTEND_PATH,'.Config.php');
Loader::import('WxpayAPI_php/php_sdk/example/log',EXTEND_PATH);
class Pay extends Controller
{
    function __construct(Request $request = null)
    {
        parent::__construct($request);
        $this -> weixin = Config::get('weixin');
        $this -> openId = $request -> param('openid');
        $this -> contact = $request -> param('contact');
        $this -> goods = $request -> param('goods');
        $this -> price = $request -> param('price');
        $this -> orderNo = $request -> param('order_no');

    }

    public function index(Request $request){
        if(empty($this->openId) || empty($this->price) || empty($this->goods) || substr($this->contact,strpos($this -> contact,':')) > 0){
            return json(['code' => 2,'msg' => ReturnCode::$return_code[2]]);
        }
//        $goodsData = ['order_id' => uuid(),'order_info' => $this->goods];
//        OrderInfo::create($goodsData);
//        $goodsD = OrderInfo::where($goodsData)->find();

//        halt($goodsD->order_id);
//        $orderuuID = uuid();

//        die;
        $order_no = $this->order_number($this->openId);
        $data = [
            'appid'=>$this->weixin['appid'],
            'body' => '商品--奶茶',
//            'detail' => $this->goods,
            'attach' => '"order_id":'.$order_no,
            'mch_id' => '1472487502',
            'nonce_str' => $this->nonce_str(),         //随机字符串
            'notify_url' => (string)$_SERVER['REQUEST_SCHEME'].'://'.$_SERVER['SERVER_NAME'].$request->root().'/'.$request -> module().'/'.$request -> controller().'/notifyUrlApi',                    //通知地址
            'openid' => $this->openId,                             //openid
            'out_trade_no' => $order_no,        //商户订单号

//            'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],                   //终端IP 192.168.0.101
            'spbill_create_ip' => '192.168.0.101',
            'total_fee' => $this->price*100,              //金额
            'trade_type' => 'JSAPI',                    //交易类型
            'version' => '1.0'
        ];

        $sign = $this->sign($data);                      //签名

        $data['sign'] = $sign;
        $xmldata = $this->xml($data);                    //数组转化为xml
        $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';         //沙箱测试 sandboxnew

        $res = $this->http_request($url, $xmldata);      //调用支付接口
        $result = $this->getxml($res);                   //xml转数组

        if($result['RETURN_CODE'] == 'SUCCESS') {

            $time = time();
            $info = '';
            $info = array(
                'appId' => $result['APPID'],                        //小程序ID
                'timeStamp' => "" . $time . "",                      //时间戳
                'nonceStr' => $this->nonce_str(),                   //随机字符串 32位字符
                'package' => 'prepay_id=' . $result['PREPAY_ID'],   //统一下单接口返回的  prepay_id 参数值，
                'signType' => 'MD5',                                //签名算法，暂支持MD5
            );
            $info['paySign'] = $this->sign($info);
            $info['order_no'] = $order_no;
            Db::startTrans();
            try{
//                $order = Order::where('order_no','=',$order_no)->find();
//                if($order){
//                    Order::update(['update_time' => time()],['order_no' => $order_no]);
//                }
                list($msec, $sec) = explode(' ', microtime());
                $orderData = [
                    'openid'=> $this->openId,
                    'order_spec' => $this->goods,
                    'price' => $this->price,
                    'order_no' => $order_no,
                    'o_id' => date('YmdHis',time()).substr((float)sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000),4),
                    'contact' => $this -> contact,
                ];
                Order::create($orderData);
                Db::commit();
            }catch (\Exception $e) {
                //回滚事务
                Db::rollback();
            }

            $list = array('code' => 0, 'msg' => ReturnCode::$return_code[0], 'data' => $info);
        }else{
            $list = array('code' => 1, 'msg' => ReturnCode::$return_code[1]);
        }
        return json($list);

    }
    public function notifyUrlApi(){
//        $str = '{"appid":"wx4a76a81fc853c1f5","attach":"{\"order_id\":\"6393cd1a64e6ce9e08582b52a4f89c54\",\"phone\":\"1821826041\"}","bank_type":"CFT","cash_fee":"1","fee_type":"CNY","is_subscribe":"N","mch_id":"1472487502","nonce_str":"wzydQdH9OxaTLEsh","openid":"oINoI4zMoMqJMZ-nwY_j71krgTvY","out_trade_no":"6393cd1a64e6ce9e08582b52a4f89c54","result_code":"SUCCESS","return_code":"SUCCESS","return_msg":"OK","sign":"C896242ED54DC5BAE071B5DC95638A2E","time_end":"20181025170911","total_fee":"1","trade_state":"SUCCESS","trade_state_desc":"\u652f\u4ed8\u6210\u529f","trade_type":"JSAPI","transaction_id":"4200000237201810253704814884"}
//';
//        echo $this->xml(object_array(json_decode($str)));
//        die;
//        $GLOBALS['HTTP_RAW_POST_DATA'] =  '<xml>
//            <appid><![CDATA[wx4a76a81fc853c1f5]]></appid>
//            <attach><![CDATA[{"order_id":"6393cd1a64e6ce9e08582b52a4f89c54","phone":"1821826041"}]]></attach>
//            <bank_type><![CDATA[CFT]]></bank_type>
//            <cash_fee><![CDATA[1]]></cash_fee>
//            <fee_type><![CDATA[CNY]]></fee_type>
//            <is_subscribe><![CDATA[N]]></is_subscribe>
//            <mch_id><![CDATA[1472487502]]></mch_id>
//            <nonce_str><![CDATA[wzydQdH9OxaTLEsh]]></nonce_str>
//            <openid><![CDATA[oINoI4zMoMqJMZ-nwY_j71krgTvY]]></openid>
//            <out_trade_no><![CDATA[6393cd1a64e6ce9e08582b52a4f89c54]]></out_trade_no>
//            <result_code><![CDATA[SUCCESS]]></result_code>
//            <return_code><![CDATA[SUCCESS]]></return_code>
//            <return_msg><![CDATA[OK]]></return_msg>
//            <sign>C896242ED54DC5BAE071B5DC95638A2E</sign>
//            <time_end><![CDATA[20181025170911]]></time_end>
//            <total_fee><![CDATA[1]]></total_fee>
//            <trade_state><![CDATA[SUCCESS]]></trade_state>
//            <trade_state_desc><![CDATA[支付成功]]></trade_state_desc>
//            <trade_type><![CDATA[JSAPI]]></trade_type>
//            <transaction_id><![CDATA[4200000237201810253704814884]]></transaction_id>
//        </xml>';
//        $GLOBALS['HTTP_RAW_POST_DATA'] = isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] : file_get_contents('php://input');

        Log::DEBUG("xml :".$GLOBALS['HTTP_RAW_POST_DATA']);
        $cofing  = new \WxPayConfig();
        Log::DEBUG("begin notify");
        $notify = new \PayNotifyCallBack();
        $notify ->Handle($cofing,false);
    }
    //取消订单
    public function orderdel(){
        if(empty($this->openId) || empty($this->orderNo)){
            return json(['code'=>2,'msg'=>ReturnCode::$return_code[2]]);
        }
        $where = ['openid' => $this->openId,'order_no' => $this->orderNo];
        $has = Order::where($where)->find();
        if(!$has){
            return json(['code'=>10,'msg'=>ReturnCode::$return_code[10]]);
        }
        $res = Order::destroy($where);
        if($res){
            return json(['code'=>0,'msg'=>ReturnCode::$return_code[0]]);
        }
        return json(['code'=>5,'msg'=>ReturnCode::$return_code[5]]);
    }
    private function order_number($openid){
        //date('Ymd',time()).time().rand(10,99);//18位
        return md5($openid.time().rand(10,99));//32位
    }


    //随机32位字符串
    public function nonce_str($value='')
    {
        $result = '';
        $str = 'QWERTYUIOPASDFGHJKLZXCVBNMqwertyuioplkjhgfdsamnbvcxz';
        for($i = 0; $i < 32; $i++){
            $result .= $str[rand(0,48)];
        }
        return $result;
    }

    //计算签名
    public function sign($data)
    {
        # code...
//        $weixinpay = Config::get('weixinpay');
         $key = '222dbcbeeba2fa6db49c69261bb36d6b';
//        $key = $weixinpay['key'];
        //步骤一： 按字典序排列参数
        ksort($data);
        $buff = "";
        foreach ($data as $k => $val) {
            # code...
            if($k != "sign" && $val != "" && !is_array($val)){
                $buff .= $k."=".$val."&";
            }
        }
        $buff = trim($buff,"&");
        //步骤二：在string后拼接key
        $string = $buff."&key=".$key;
        //步骤三： MD5加密
        // var_dump($string);
        $string = md5(urldecode($string));
        //步骤四：所有字符转大写

        $sign = strtoupper($string);
        return $sign;

    }

    //返回xml数据
    public function xml($data)
    {
        # code...
        // ksort($data);
        //数据拼接
        $data_xml = "<xml>";
        foreach ($data as $key => $val) {
            # code...
            if($key == 'sign' || $key == 'version'){
                $data_xml .= "<".$key.">".$val."</".$key.">";
            }else if(is_array($val)){
                $data_xml .= "<".$key."><![CDATA[".json_encode($val)."]]></".$key.">";
            }else{
                $data_xml .= "<".$key."><![CDATA[".$val."]]></".$key.">";
            }
        }
        $data_xml .="</xml>";
        return $data_xml;
    }

    // 创建CURL
    private static function http_request($url,$rawData, $second = 30)
    {
        $ch = curl_init();
        //设置超时
        curl_setopt($ch, CURLOPT_TIMEOUT, $second);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); //严格校验
        //设置header
        curl_setopt($ch, CURLOPT_HEADER, FALSE);
        //要求结果为字符串且输出到屏幕上
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        //post提交方式
        curl_setopt($ch, CURLOPT_POST, TRUE);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $rawData);


        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 20);
        curl_setopt($ch, CURLOPT_TIMEOUT, 40);
        set_time_limit(0);


        //运行curl
        $data = curl_exec($ch);
        //返回结果
        if ($data) {
            curl_close($ch);
            return $data;
        } else {
            $error = curl_errno($ch);
            curl_close($ch);
            throw new WxPayException("curl出错，错误码:$error");
        }
    }

    //获取 xml
    private function getxml($xml)
    {
        # code...
        $p = xml_parser_create();
        xml_parse_into_struct($p, $xml, $vals, $index);
        xml_parser_free($p);
        $data = [];
        foreach ($index as $key => $value) {
            if($key == 'xml' || $key == 'XML') continue;
            $tag = $vals[$value[0]]['tag'];
            if(isset($vals[$value[0]]['value'])){
                $value = $vals[$value[0]]['value'];
            }

            $data[$tag] = $value;
        }
        return $data;
    }


}